/*
* detect_face_test.cpp
* client端多线程人脸检测测试
*  Created on: 2018年05月13日
*      Author: guyadong
*/
#include <iostream>
#include <regex>
#include "sample_log.h"
#include "FaceApiIfClient.h"
#include "BaseCmdParam.h"
#include "gfaux_tools.h"
#include "ThreadPool.h"
using namespace gdface;
using namespace net::gdface::sdk;
using namespace gdface::ui;
using namespace gdface::log;
using namespace codegen;

namespace gdface {
	class MtConfig : public BaseClientConfig {
	public:
		std::string folder;
		MtConfig() {
			// --folder 指定要检测的图像文件
			cmdparam.add<std::string>("folder", 'f', "jpeg image folder for detection", false,"images");
		}
	protected:
		void afterParse() {
			BaseClientConfig::afterParse();
			folder = cmdparam.get<std::string>("folder");
		}
	};
	/* 线程池 */
	class MiniThreadPool :public ThreadPool {
	public:
		/* 线程池构造函数,线程数默认初始化为与CPU核数相同 */
		MiniThreadPool(size_t threads = 0) :ThreadPool(0 == threads ? std::thread::hardware_concurrency() : threads) {
		}
		virtual ~MiniThreadPool() = default;
	};
	// 列出指定目录下名字后缀匹配suffix的所有文件(不包含目录)
	// sub为true时为目录递归
	// 返回每个文件的全路径名
	std::vector<std::string> ls(const std::string&dir_name, const std::string& suffix, bool sub = false) {
		return for_each_file(dir_name, [&](const char*, const char* name)->bool {
			return end_with(std::string(name), suffix);
		});
	}
}

int main(int argc, char *argv[]) {

	MtConfig param;
	param.parse(argc, argv);

	auto client = FaceApiIfClient(param.host, param.port);

	MiniThreadPool thread_pool;
	try {
		SAMPLE_OUT("connect service:{}@{} ...", param.port, param.host);
		SAMPLE_OUT("IMAGE FOLDER:{}",param.folder);
		std::vector<CodeInfo> codes;
		auto files = ls(param.folder,".jpg");
		throw_if_msg(files.empty(), "NOT FOUND image file")
		SAMPLE_OUT("{} files FOUND", files.size());
		std::vector<std::string> jpeg_datas;
		for (auto f : files) {
			auto d = gdface::load_string(f.c_str());
			SAMPLE_OUT("LOAD IMAGE FILE:{},{} bytes", get_file_name(f),d.size());
			jpeg_datas.push_back(d);
		}
		// 运算次数
		int runCount = 2000;
		std::vector< std::future<void> > futures(runCount);
		for (int i = 0; i < runCount; ++i) {
			// 向线程池加入任务
			futures[i] = thread_pool.enqueue([&]() {
				auto idx = i%jpeg_datas.size();
				stl_wrapper<std::vector<CodeInfo>> codes;
				client.detectFace(codes, jpeg_datas[idx]);
				showText(*codes, sample_format("{}:detectFace response: ",i));
			});
		}
		// 等待所有线程结束
		for (auto &f: futures) {
			f.get();
		}
	}
	catch (std::exception& tx) {
		SAMPLE_ERR("ERROR: {}", tx.what());
	}
}